<template>
  <section>
    <!-- 面包屑导航 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>商品管理</el-breadcrumb-item>
      <el-breadcrumb-item>分类参数</el-breadcrumb-item>
    </el-breadcrumb>

    <!-- 卡片视图区域 -->
    <el-card>
      <!-- 警告条 -->
      <el-alert
        show-icon
        title="注意: 只允许为第三级分类设置相关数据"
        type="warning"
        :closable="false"
      ></el-alert>
      <!-- 添加角色按钮区域
      使用栅格系统, 使按钮单独成行 -->
      <el-row>
        <el-col>
          <span>选择商品分类: </span>
          <!-- 选择商品分类的级联选择器 -->
          <!-- cascader级联选择器
          options 指定数据源
          props 配置对象
          v-model 所有选择项value值组成的数组
          clearable 选择框有内容时展示 清除小按钮 -->
          <el-cascader
            v-model="selectedCateKeys"
            :options="cateList"
            :props="cateProps"
            @change="handleChange"
            clearable
            class="cat_cascader"
          ></el-cascader>
        </el-col>
      </el-row>

      <!-- tab 页签区域 -->
      <el-tabs v-model="activeName" @tab-click="handleClick">
        <el-tab-pane label="动态参数" name="many">
          <el-button
            type="primary"
            size="mini"
            :disabled="isBtnDisabled"
            @click="addDialogVisible = true"
            >添加参数</el-button
          >
          <!-- 动态参数表格 -->
          <el-table border stripe :data="manyTableData">
            <!-- 展开行 -->
            <el-table-column type="expand">
              <template slot-scope="scope">
                <!-- 循环渲染Tag标签 -->
                <el-tag v-for="(item, i) in scope.row.attr_vals" :key="i" closable @close="handleClose(i, scope.row)">{{item}}</el-tag>
                <!-- 输入框 -->
                <el-input
                  class="input-new-tag"
                  v-if="scope.row.inputVisible"
                  v-model="scope.row.inputValue"
                  ref="saveTagInput"
                  size="small"
                  @keyup.enter.native="handleInputConfirm(scope.row)"
                  @blur="handleInputConfirm(scope.row)"
                >
                <!-- 添加按钮 -->
                </el-input>
                <el-button v-else class="button-new-tag" size="small" @click="showInput(scope.row)">+ New Tag</el-button>
              </template>
            </el-table-column>

            <el-table-column type="index" label="#"></el-table-column>
            <el-table-column prop="attr_name" label="参数名称"></el-table-column>
            <el-table-column label="操作">
              <template slot-scope="scope">
                <el-button size="mini" type="primary" icon="el-icon-edit" @click="showEditDialog(scope.row.attr_id)">编辑</el-button>
                <el-button size="mini" type="danger" icon="el-icon-delete" @click="removeParams(scope.row.attr_id)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>

        <el-tab-pane label="静态属性" name="only">
          <el-button
            type="primary"
            size="mini"
            :disabled="isBtnDisabled"
            @click="addDialogVisible = true"
            >添加属性</el-button
          >
          <!-- 静态参数表格 -->
          <el-table border stripe :data="onlyTableData">
            <!-- 展开行 -->
            <el-table-column type="expand">
              <template slot-scope="scope">
                <!-- 循环渲染Tag标签 -->
                <el-tag v-for="(item, i) in scope.row.attr_vals" :key="i" closable @close="handleClose(i, scope.row)">{{item}}</el-tag>
                <!-- 输入框 -->
                <el-input
                  class="input-new-tag"
                  v-if="scope.row.inputVisible"
                  v-model="scope.row.inputValue"
                  ref="saveTagInput"
                  size="small"
                  @keyup.enter.native="handleInputConfirm(scope.row)"
                  @blur="handleInputConfirm(scope.row)"
                >
                <!-- 添加按钮 -->
                </el-input>
                <el-button v-else class="button-new-tag" size="small" @click="showInput(scope.row)">+ New Tag</el-button>
              </template>
            </el-table-column>
            
            <el-table-column type="index" label="#"></el-table-column>
            <el-table-column prop="attr_name" label="参数名称"></el-table-column>
            <el-table-column label="操作">
              <template slot-scope="scope">
                <el-button size="mini" type="primary" icon="el-icon-edit" @click="showEditDialog(scope.row.attr_id)">编辑</el-button>
                <el-button size="mini" type="danger" icon="el-icon-delete" @click="removeParams(scope.row.attr_id)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>
      </el-tabs>
    </el-card>

    <!-- 添加参数的对话框(添加动态参数或静态参数) -->
    <el-dialog :title="'添加' + titleText" :visible.sync="addDialogVisible" width="50%" @close="addDialogClosed">
      <!-- 添加参数表单对话框 -->
      <el-form :model="addForm" :rules="addFormRules" ref="addFormRef" label-width="100px">
        <el-form-item :label="titleText" prop="attr_name">
          <el-input v-model="addForm.attr_name"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="addParams">确 定</el-button>
      </span>
    </el-dialog>

    <!-- 修改参数的对话框(添加动态参数或静态参数) -->
    <el-dialog :title="'添加' + titleText" :visible.sync="editDialogVisible" width="50%" @close="editDialogClosed">
      <!-- 添加参数表单对话框 -->
      <el-form :model="editForm" :rules="editFormRules" ref="editFormRef" label-width="100px">
        <el-form-item :label="titleText" prop="attr_name">
          <el-input v-model="editForm.attr_name"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="editDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="editParams">确 定</el-button>
      </span>
    </el-dialog>
  </section>
</template>

<script type="text/ecmascript-6">
export default {
  data() {
    return {
      cateList: [], // 所有商品列表
      cateProps: {
        // 级联选择器配置对象(对应数据源中的属性)
        value: 'cat_id', // 指定选项值
        label: 'cat_name', // 选项名称
        children: 'children', // 选项的子选项来源数据
        expandTrigger: 'hover',
      },
      selectedCateKeys: [], // 选中的父级分类的ID数组,可选择两级

      activeName: 'many', // 被激活的页面名称, 绑定对应页签中的 name属性
      manyTableData: [], // 动态页签参数属性的数据
      onlyTableData: [], // 静态页签参数属性的数据

      addDialogVisible: false, // 添加对话框
      addForm: {
        // 添加参数表单项数据对象
        attr_name: '',
      },
      addFormRules: {  // 添加表单的验证规则
        attr_name: [
          { required: true, message: '请输入参数名称', trigger: 'blur' }
        ]
      },

      editDialogVisible: false, // 修改对话框
      editForm: {},   // 修改的表单数据, 由点击后使用作用域插槽进行传入
      editFormRules: {  // 添加表单的验证规则
        attr_name: [
          { required: true, message: '请输入参数名称', trigger: 'blur' }
        ]
      },
    }
  },
  created() {
    this.getCateList()
  },
  computed: {
    /* 按钮是否被禁用 */
    isBtnDisabled () {
      if (this.selectedCateKeys.length !== 3) {
        return true 
      } 
      return false
    },

    /* 当前选中的三级分类的ID */
    cateId () {
      if (this.selectedCateKeys.length === 3) {
        return this.selectedCateKeys[2]
      }
      return null  // 未选择三级分类
    },

    /* 动态计算标题的文本 */
    titleText() {
      if (this.activeName === 'many') {
        return '动态参数'
      }
      return '静态属性'
    }
  },
  methods: {
    /* 获取所有商品分类列表 */
    async getCateList() {
      const { data: res } = await this.$http.get('categories')
      if (res.meta.status !== 200) {
        return this.$message.error('获取商品分类失败!')
      }
      this.cateList = res.data
      // console.log(res)
    },

    /* 级联选择器选项变化时触发该回调 */
    handleChange() {
      this.getParamsData()
    },
    /* 级联选择器选择后,获取列表数据 */
    async getParamsData() {
      // 若选中的不是三级分类则不处理并发出提示信息
      if (this.selectedCateKeys.length !== 3) {
        this.selectedCateKeys = [] // 此时直接将刚刚选择后双向绑定的数据清空,即清空输入框(不显示选中选项)
        this.manyTableData = []  // 重置之前可能残留的动态页签对应的参数
        this.onlyTableData = []  // 重置之前可能残留的静态页签对应的参数
        return null // 终止逻辑执行
      }
      // 此时选中的是三级分类项
      // 根据所分类的ID, 和当前所处的面板, 获取对应的参数
      // 请求中携带 第三级分类的ID
      const { data: res } = await this.$http.get(
        `categories/${this.cateId}/attributes`,
        {
          params: { sel: this.activeName }  // many代表动态参数; only代表静态参数
        }
      )
      if (res.meta.status !== 200) {
        return this.$message.error('获取参数列表失败!')
      }

      // 将参数加工成可以遍历的数组格式
      res.data.forEach(item => {
        // 原数据以空格分隔, 将数据结构重新处理(以空格为分割标志分割成数组形式),更新保存到原属性上
        item.attr_vals = item.attr_vals ? item.attr_vals.split(' ') : []  // 判断是否为空字符串(空字符串时不处理会被分割成[''])
        // 加工数据,为每一项添加自定义属性inputVisible(解决在data定义该属性导致多个文本框共用同一个inputVisible导致的数据污染问题)
        item.inputVisible = false  // 控制文本框的显示隐藏切换  默认隐藏
        item.inputValue = ''  // 自定义属性inputValue 用于表示文本框初始输入值为 ''
      })
      // console.log(res)
      // 根据激活页签,对返回的参数进行赋值
      if (this.activeName === 'many') {   // 动态页签
        this.manyTableData = res.data
      } else {  // 静态页签
        this.onlyTableData = res.data
      }
    },

    /* 点击页签 */
    handleClick () {
      this.getParamsData()
    },

    /* 添加页签关闭 */
    addDialogClosed() {
      this.$refs.addFormRef.resetFields()
    },
    /* 点击添加参数 */
    addParams () {
      this.$refs.addFormRef.validate(async valid => {
        if (!valid) return null
        const { data: res } = await this.$http.post(
          `categories/${this.cateId}/attributes`,
          {
            attr_name: this.addForm.attr_name,
            attr_sel: this.activeName
          }
        )
        if (res.meta.status !== 201) {
          return this.$message.error('添加参数失败!')
        }
        this.$message.success('添加参数成功!')
        this.addDialogVisible = false
        this.getParamsData()
      })
    },


    /* 关闭修改对话框 */
    editDialogClosed() {
      this.$refs.editFormRef.resetFields()
    },
    /* 点击修改对话框 */
    async showEditDialog(attrId) {
      // 查询当前参数的信息  请求中携带  第三级分类的ID 参数属性ID
      const { data: res } = await this.$http.get(
        `categories/${this.cateId}/attributes/${attrId}`,
        {
          params: { attr_sel: this.activeName }
        }
      )
      if (res.meta.status !== 200) {
        return this.$message.error('添加参数失败!')
      }
      this.editForm = res.data
      this.editDialogVisible = true
    },
    /* 点击修改按钮 */
    editParams () {
      this.$refs.editFormRef.validate(async valid => {
        if (!valid) return null
        const { data: res } = await this.$http.put(
          `categories/${this.cateId}/attributes/${this.editForm.attr_id}`,
          {
            attr_name: this.editForm.attr_name,  // 新修改的属性名
            attr_sel: this.activeName
          }
        )
        if (res.meta.status !== 200) {
          return this.$message.error('修改参数失败!')
        }
        this.$message.success('修改参数成功!')
        this.getParamsData()
        this.editDialogVisible = false
      })
    },

    /* 删除选项 */
    async removeParams(attrId) {
      const confirmResult = await this.$confirm(
        '此操作将永久删除该参数, 是否继续?',
        '提示',
        {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }
      ).catch(err => err)
      if (confirmResult !== 'confirm') {
        return this.$message.info('已取消删除!')
      }
      // 删除的业务逻辑
      const { data: res } = await this.$http.delete(
        `categories/${this.cateId}/attributes/${attrId}`,
      )
      if (res.meta.status !== 200) {
        return this.$message.error('删除参数失败!')
      }
      this.$message.success('删除参数成功!')
      this.getParamsData()
    },


    /* 点击按钮,展示文本输入框 */
    showInput(row) {
      row.inputVisible = true // 数据改变,此时页面还没有立即渲染完毕,不能得到最新的DOM节点,若此时对该还未渲染出的节点进行操作就会导致报错
      // $nextTick : 数据改变后等待当前页面元素被重新渲染之后,再执行该回调; 此时可以拿到最新的DOM节点进行操作
      this.$nextTick(() => {
        this.$refs.saveTagInput.$refs.input.focus()  // 获取刚生成的input节点执行focus(), 让文本框自动获取焦点!!! (问题点)
      })
    },

    /* 文本框失去焦点, 或按下了 Enter 都会触发 */
    async handleInputConfirm(row) {
      if (row.inputValue.trim().length === 0) {  // 输入的全是空格
        row.inputValue = ''   // 清空输入框
        row.inputVisible = false   // 不可见
        return null
      }
      // 输入合法
      row.attr_vals.push(row.inputValue.trim())  // 将内容push到标签循环依赖源数据中
      row.inputValue = ''
      row.inputVisible = false

      // 发起请求, 保存这一次的操作
      this.saveAttrVals(row)
    },
    /* 将对 attr_vals 的操作, 保存到数据库中 */
    async saveAttrVals(row) {
      const { data: res } = await this.$http.put(
        `categories/${this.cateId}/attributes/${row.attr_id}`,
        {
          attr_name: row.attr_name,
          attr_sel: row.attr_sel,
          attr_vals: row.attr_vals.join(' ')  // 将之前加工的数组还原到最初的 字符串格式 数据之间以 空格 链接
        }
      )
      if (res.meta.status !== 200) {
        return this.$message.error('修改参数失败!')
      }
      this.$message.success('修改参数成功!')
    },

    /* 删除对应的标签的选项 */
    handleClose(i, row) {
      row.attr_vals.splice(i, 1)  // 操作的是传过来的引用类型数据!!! 无需返回
      this.saveAttrVals(row)  // 传入最新的row 发送请求进行更新!
    }
  },
}
</script>

<style scoped lang="less">
.el-row {
  margin: 15px 0;
}

.cat_cascader {
  width: 30%;
}

.el-tag {
  margin: 10px;
}

.input-new-tag {
  width: 120px;
}
</style>
